package chen.huai.jie.spring.xmlconfig.mybatis;

import org.apache.ibatis.type.TypeHandler;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;

public class SelectBuilder implements SqlBuilder {
    public SelectBuilder() {
    }

    public String buildSql(Class<?> mapper, Method method, EntityPortray entityPortray) {
        StringBuilder builder = new StringBuilder();
        Class<?> returnType = MapperUtils.getReturnType(method, mapper);
        EntityPortray returnPortray = MapperUtils.getEntityPortray(mapper, returnType);
        Map<String, String> columnMap = entityPortray.getColumnMap();
        Map<String, Class<? extends TypeHandler>> typeHandlers = entityPortray.getColumnTypeHandlers();
        Map<String, Class<?>> parameterMap = MapperUtils.getParameters(method);
        if (columnMap.values().contains(MapperConfig.getDelFlagColumn()) && method.getName().endsWith("Valid") && !parameterMap.containsKey(MapperConfig.getDelFlagColumn())) {
            parameterMap.put("__del_flag__", String.class);
        }

        builder.append("<script>select ").append((String) returnPortray.getColumnMap().values().stream().collect(Collectors.joining(","))).append(" FROM ").append(entityPortray.getName()).append("<where>");
        parameterMap.forEach((param, paraType) -> {
            if (!PageRequest.class.isAssignableFrom(paraType)) {
                if (Collection.class.isAssignableFrom(paraType)) {
                    builder.append(" and ").append((String) columnMap.get(param)).append(" in ").append("<foreach item=\"item\" index=\"index\" collection=\"").append(param).append("\" open=\"(\" separator=\",\" close=\")\">").append("#{item}</foreach>");
                } else if (param.equals("__del_flag__")) {
                    builder.append(" and ").append(MapperConfig.getDelFlagColumn()).append("=0");
                } else {
                    builder.append(" and ").append((String) columnMap.get(param)).append("=").append(MapperUtils.buildTypeValue(param, paraType, "", (Class) typeHandlers.get(param)));
                }

            }
        });
        builder.append("</where>");
        OrderBy orderBy = (OrderBy) method.getAnnotation(OrderBy.class);
        if (orderBy != null) {
            if (!orderBy.orderSql().isEmpty()) {
                builder.append(orderBy.orderSql());
            } else if (!orderBy.value().isEmpty()) {
                builder.append(" order by ").append((String) columnMap.getOrDefault(orderBy.value(), orderBy.value())).append(orderBy.desc() ? " desc " : " asc ");
            }
        }

        builder.append("</script>");
        return builder.toString();
    }
}
